//
// Created by xsh on 2025/5/27.
//
// 仿FL studio 3xosc 和caustic的subsynth
#include <jni.h>
#include <math.h>
#include <iostream>
#include <string>
#include "subsynth.h"
#include "../../../../common/include/LogUtil.h"
#include "../../../../common/include/MidiTool.cpp"

SubSynth::SubSynth()
{
    adsr.attackTime = 0;
    adsr.decayTime = 0;
    adsr.sustainLevel = 1;
    adsr.releaseTime = 0;

    adsrMaxTime.maxAttack = 5;
    adsrMaxTime.maxDecay = 3;
    adsrMaxTime.maxRelease = 3;

    osc1.frequency = 261.63;
    osc1.amp = 1;
    osc1.waveform = WaveType::SINE;
    osc1.currentPhase = 0.0;
    osc2.frequency = 261.63;
    osc2.amp = 1;
    osc2.waveform = WaveType::SINE;
    osc2.currentPhase = 0.0;
    // lfo初始化
    //lfo.setFrequency(1.0);
    //lfo.setAmp(0.5);
    lfo.setWaveType(LFO::SINE);
}
void SubSynth::Oscillator::generate(short *buffer, int numSamples, double sampleRate)
{
    double phaseIncrement = 2.0 * M_PI * frequency / sampleRate;

    for (int i = 0; i < numSamples; ++i) {
        double waveValue = 0.0;

        switch (waveform) {
            case SINE:
                waveValue = sin(currentPhase);
                break;
            case TRAN: {
                double modPhase = fmod(currentPhase, 2 * M_PI);
                if (modPhase < M_PI)
                    waveValue = 2.0 * modPhase / M_PI - 1.0;
                else
                    waveValue = 3.0 - 2.0 * modPhase / M_PI;
                break;
            }
            case SAWTOOTH:
                waveValue = 2.0 * (fmod(currentPhase, 2 * M_PI) / (2 * M_PI)) - 1.0;
                break;
        }

        // 写入缓冲区
        buffer[i] += static_cast<short>(amp * 32767.0 * waveValue);
        //LOGD(tag,"osc_amp:%f",amp);
        // 更新相位
        currentPhase += phaseIncrement;
        if (currentPhase >= 2 * M_PI) currentPhase -= 2 * M_PI;
    }
}

void SubSynth::setWaveForm(int oscIndex,WaveType type)
{
    if(oscIndex == 0){osc1.waveform = type;}
    else if(oscIndex ==1){osc2.waveform = type;}
}

double SubSynth::genWave(short* buffer, int numSamples,double phase, double sampleRate)
{
    memset(buffer, 0, sizeof(short) * numSamples); // 清空 buffer
    if(apply_lfo)
    {
        // 不知道为什么这一行没被打印
        //LOGD(tag,"in_synth_gen,lfo_type:%d",current_lfo_type);
        if(current_lfo_type == LfoType::VOL)
        {
            for (int i = 0; i < numSamples; ++i) {
                double lfoValue = lfo.generateSample(sampleRate);  // 获取 LFO 值

                // 应用 LFO 到振荡器的音量
                osc1.amp = lfoValue;
                osc2.amp = lfoValue;
                //osc1.amp = std::fmax(0.0, 1.0 + lfoValue);  // 音量范围 [0.0, 2.0]
                //osc2.amp = std::fmax(0.0, 1.0 + lfoValue);  // 音量范围 [0.0, 2.0]
                //LOGD(tag,"lfoValue%f",lfoValue);
                // 生成振荡器的声音
                osc1.generate(buffer + i, 1, sampleRate);
                osc2.generate(buffer + i, 1, sampleRate);
            }
        }
        else if (current_lfo_type == LfoType::PITCH){}
        else if(current_lfo_type == LfoType::PHASE){}
    }

    else{
        //osc1.amp = 1.0;
        //osc2.amp = 1.0;
        for (int i = 0; i < numSamples; ++i)
        {
            osc1.generate(buffer + i, 1, sampleRate);
            osc2.generate(buffer + i, 1, sampleRate);
        }
    }
    return phase;
}

SubSynth* createInstrument(){return new SubSynth();}

void SubSynth::onEvent(const char* eventName, jint value)
{
    if(strcmp(eventName,"noteOn")==0)
    {
        osc1.frequency = midiNoteToFrequency(value);
        osc2.frequency = midiNoteToFrequency(value);
    }
    else if(strcmp(eventName,"setOsc1Wave")==0)
    {
        osc1.waveform = static_cast<WaveType>(value);
        LOGD(tag,"选择osc1波形:%d",value);
    }
    else if(strcmp(eventName,"setOsc2Wave")==0)
    {
        osc2.waveform = static_cast<WaveType>(value);
        LOGD(tag,"选择osc1波形:%d",value);
    }
    else if(strcmp(eventName,"setFilter")==0)
    {
        currentFilter = static_cast<FilterType>(value);
    }
    else if(strcmp(eventName,"setCutOff")==0)
    {

    }
    else if(strcmp(eventName,"setLfoSpeed")==0)
    {
        lfo.setFrequency(lfo.frequency = value);
    }

    else if(strcmp(eventName,"setLfoType")==0)
    {
        if(value==0)
        {
            current_lfo_type = LfoType::VOL;
        }
        else if(value ==1)
        {
            current_lfo_type = LfoType::PHASE;
        }
        else if(value == 2)
        {
            current_lfo_type = LfoType::PITCH;
        }
        LOGD(tag,"onEvent(const char* eventName, jint value) call:当前lfo值%d",current_lfo_type);
    }

    LOGD(tag,"事件:%s值:%d",eventName,value);
}

void SubSynth::onEvent(const char* eventName, jdouble value)
{
    if(strcmp(eventName,"setLfoAmp")==0)
    {
        lfo.setAmp(value);
    }
    else if(strcmp(eventName,"setAmp")==0)
    {
        osc1.amp = value;
        osc2.amp = value;
    }
    else if(strcmp(eventName,"setRes")==0)
    {

    }
    else if(strcmp(eventName,"toggleFilter")==0)
    {
        apply_Filter = value;
    }
    else if(strcmp(eventName,"toggleLfo")==0)
    {
        apply_lfo = value;
        LOGD(tag,"appply_lfo:%f",value);
    }
    LOGD(tag,"事件%s值%f",eventName,value);
}
// 不知道为什么没有被调用
void SubSynth::onEvent(const char *eventName, bool value)
{
    if(strcmp(eventName,"toggleLfo")==0)
    {
        apply_lfo = value;
    }
    LOGD(tag,"开关滤波器或者LFO%d",value);
}
void SubSynth::printADSRState()
{
    //LOGD("ADSR","%s","adsr booted");
    //LOGD("Stage","%d",adsr.stage);
}
/*
void SubSynth::changeVolEnv(volEnv type,double value)
{
    switch (type) {
        case A:
            adsr.attackTime = value * SubSynth::adsrMaxTime.maxAttack; // 假设传入的是毫秒
            LOGD("ChangeAttack","%f",adsr.attackTime);
            break;
        case D:
            adsr.decayTime = value * SubSynth::adsrMaxTime.maxDecay;
            LOGD("ChangeDeacy","%f",adsr.decayTime);
            break;
        case S:
            adsr.sustainLevel = value  ; // 0-100转0.0-1.0
            LOGD("ChangeSus","%f",adsr.sustainLevel);
            break;
        case R:
            adsr.releaseTime = value * SubSynth::adsrMaxTime.maxRelease;
            LOGD("ChangeRelease","%f",adsr.releaseTime);
            break;
    }
    //__android_log_print(ANDROID_LOG_DEBUG, "Osc3Event changeVolEnv", "%d",type);
    //__android_log_print(ANDROID_LOG_DEBUG, "Osc3Event changeVolEnv", "%d",value);
}*/
/*
void SubSynth::noteOn() {
    if (adsr.stage == ADSR::IDLE || adsr.stage == ADSR::RELEASE) {
        adsr.stage = ADSR::ATTACK;
        adsr.currentTime = 0.0f;
        adsr.isNoteOn = true;
    }
}

void SubSynth::noteOff() {
    if (adsr.stage != ADSR::IDLE && adsr.isNoteOn) {
        adsr.stage = ADSR::RELEASE;
        adsr.currentTime = 0.0f;
        adsr.isNoteOn = false;
    }
}*/

/*
double SubSynth::genWave(short* outputBuffer, int numSamples, double currentPhase, double freq, double p_amp, double sRate)
{
    // 计算包络
    for(int i=0;i<numSamples;++i) {
        double env = 1.0; // 0.0f
        if (useVolEnv)
        {
            switch (adsr.stage) {
                case ADSR::ATTACK: {
                    adsr.currentTime += 1.0 / sRate;
                    if (adsr.currentTime >= adsr.attackTime) {
                        adsr.stage = ADSR::DECAY;
                        adsr.currentTime = 0.0f;
                        env = 1.0f;
                    } else {
                        env = adsr.currentTime / adsr.attackTime;
                    }
                    break;
                }
                case ADSR::DECAY: {
                    adsr.currentTime += 1.0 / sRate;
                    if (adsr.currentTime >= adsr.decayTime) {
                        adsr.stage = ADSR::SUSTATIN;
                        adsr.currentTime = 0.0f;
                        env = adsr.sustainLevel;
                    } else {
                        double decayFactor = adsr.currentTime / adsr.decayTime;// 原float
                        env = 1.0f - (1.0f - adsr.sustainLevel) * decayFactor;
                    }
                    break;
                }
                case ADSR::SUSTATIN: {
                    env = adsr.sustainLevel;
                    if (!adsr.isNoteOn) {
                        adsr.stage = ADSR::RELEASE;
                        adsr.currentTime = 0.0f;
                    }
                    break;
                }
                case ADSR::RELEASE: {
                    adsr.currentTime += 1.0f / sRate;
                    if (adsr.currentTime >= adsr.releaseTime) {
                        adsr.stage = ADSR::IDLE;
                        env = 0.0f;
                    } else {
                        env = adsr.sustainLevel * (1.0f - adsr.currentTime / adsr.releaseTime);
                    }
                    break;
                }
                case ADSR::IDLE: {
                    env = 0.0f;
                    break;
                }

            }
           // LOGD("env","%f",env);
            printADSRState();

        }
        double waveValue = 0.0;
        double phaseIncrement = 2.0 * M_PI * freq / sRate;
        switch (currentWaveType) {
            case SINE:
                waveValue = sin(currentPhase);
                break;
            case SAWTOOTH:
                waveValue = 2.0 * (fmod(currentPhase, 2 * M_PI) / (2 * M_PI)) - 1.0;
                break;
            case TRAN: {
                double modPhase = fmod(currentPhase, 2 * M_PI);
                waveValue = (modPhase < M_PI) ?
                            (2.0 * modPhase / M_PI - 1.0) :
                            (3.0 - 2.0 * modPhase / M_PI);
                break;
            }
        }
        // 应用包络和振幅
        outputBuffer[i] = static_cast<short>(p_amp * env * 32767.0 * waveValue);
        currentPhase += phaseIncrement;
        if (currentPhase >= 2 * M_PI) currentPhase -= 2 * M_PI;
    }
    return currentPhase;
}*/